#ifndef LOG_H
#define LOG_H

// Purpose: Defines global flexible logging capabilities for the engine.
// Status:  Still in design-stage

//TODO: Could have separate logs for each level (e.g., DebugLog, ErrorLog, WarningLog etc.)
//TODO: Possible features:
//			Filename and line-number logging.

//TODO: Work out how to specify prefixes to append to OutStream output

#include <iostream>
#include <fstream>
//#include <sstream>

#include <utils/String.h>

//A wrapper class for an ostream
class OutStream : public std::ostream
{
	std::ostream* m_pNewStream;
public:
	//Default constructor initialises the streambuffer to std::cout
	OutStream() : std::ostream( std::cout.rdbuf() ), m_pNewStream(0) {}
	
	OutStream( std::ostream& stream )
	 : std::ostream( stream.rdbuf() ), m_pNewStream(0) {}
	 
	OutStream( String sFilename )
	{
		//Create a new file stream to output to
		m_pNewStream = new std::ofstream( sFilename.c_str() );
		//Set the streambuffer of the superclass
		this->init( m_pNewStream->rdbuf() );
	}
	
	~OutStream()
	{
		if ( m_pNewStream )
			delete m_pNewStream;
	}
	
	void redirect( std::ostream& destStream )
	{
		if ( m_pNewStream ) {
			delete m_pNewStream;
			m_pNewStream = 0;
		}
		//Set the streambuffer of the superclass
		this->init( destStream.rdbuf() );
	}
	
	void redirect( String sFilename )
	{
		if ( m_pNewStream )
			delete m_pNewStream;
		m_pNewStream = new std::ofstream( sFilename.c_str() );
		//Set the streambuffer of the superclass
		this->init( m_pNewStream->rdbuf() );
	}
};

namespace report {
	//Our custom output streams
	
	OutStream error( std::cerr );
	OutStream warning( std::cerr );
	OutStream debug;
} //namespace log

/*

Engine::Log::spit( 

enum LogLevel {
	LOG_LEVEL_ERROR = 0,
	LOG_LEVEL_WARNING,
	LOG_LEVEL_INFO,
	LOG_LEVEL_DEBUG
};

if ( LogLevelToSpitOut >= MsgLevel )
	Spit out message

template< LogLevel T_iLevel >
class Log
{
	template< bool T_bWrite >
	inline void write ( String sMsg )
	
	std::ostream* m_pLog;
	
public:
	
	Log() : m_pLog( &std::cout ) {}
	
	void redirectLog( std::ostream& osDestination ) { m_osLog = &osDestination; }
	void setPrecision( unsigned iPrecision )        { m_osLog.precision( iPrecision ); }
	
	class Base
	{
	      char strVal[100];
	      public:
	      Base(){ strcpy(strVal,"");}
	      Base(char *val){ strcpy(strVal,val);}
	      ~Base(){*strVal = '\0';}
	      friend istream& operator >>(istream &is,Base &obj);
	      friend ostream& operator <<(ostream &os,const Base &obj);
	};
	std::istream& operator >>(istream &is,Base &obj)
	{
	      is>>strVal;
	      return is;
	}
	std::ostream& operator << (ostream& osResult, const Log& log)
	{
	      os << obj.strVal;
	      return os;
	}
	
	template< LogLevel T_iLogType >
	inline void write( String sMsg )
	{
		_write
	}
	
	template< >
	inline void write< LOG_LEVEL_ERROR >( String sMsg )
	{
		
	}
	
	template< unsigned T_iLogType >
	inline void write( String sMsg ) {}
	
};
*/
#endif // LOG_H
